package org.linlinjava.litemall.admin.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.yulichang.toolkit.MPJWrappers;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import org.linlinjava.litemall.admin.beans.annotation.LogAnno;
import org.linlinjava.litemall.admin.service.AdminSubscribeService;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.core.validator.Order;
import org.linlinjava.litemall.core.validator.Sort;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.dto.LitemallOrderDto;
import org.linlinjava.litemall.db.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

/**
 * 管理订阅数据控制器
 *
 * @author yliyun
 * @date 2022/09/14
 */
@RestController
@RequestMapping("/admin/subscribeStatistic")
@Validated
public class AdminSubscribeStatisticsController {
    /**
     * 管理订阅服务
     */
    @Autowired
    private AdminSubscribeService adminSubscribeService;

    /**
     * 卢米埃订阅服务
     */
    @Autowired
    private LumiereSubscribeService lumiereSubscribeService;

    /**
     * litemall订单服务
     */
    @Autowired
    private LitemallOrderService litemallOrderService;

    /**
     * litemall订货服务
     */
    @Autowired
    private LitemallOrderGoodsService litemallOrderGoodsService;

    /**
     * litemall用户服务
     */
    @Autowired
    private LitemallUserService litemallUserService;

    @Autowired
    private LitemallShopService litemallShopService;

    @Autowired
    private LumiereSubscribeUserService lumiereSubscribeUserService;

    @ApiOperation("所有订阅")
    @GetMapping("/subscribe-list")
    @LogAnno
    public ResponseUtil.Response statistic(){
        return ResponseUtil.ok(lumiereSubscribeService.list());
    }


    @ApiOperation("统计")
    @GetMapping("/statistic")
    @LogAnno
    public Object statistic(String startTime, String endTime, Integer shopId,Integer subscribeId){

        //根据地区查询regionId中是否存在
            //订阅总数
            Integer total = adminSubscribeService.querySubscribeNum(startTime,endTime,shopId,subscribeId);

            //总人数
            Integer userTotal = adminSubscribeService.queryUserTotal(startTime,endTime,shopId,subscribeId);

            //总额和总积分
            Double totalPrice = adminSubscribeService.queryTotalPrice(startTime,endTime,shopId,subscribeId);
            totalPrice=totalPrice==null?0.00:totalPrice;

            Integer totalPoint = adminSubscribeService.queryTotalPoint(startTime,endTime,shopId,subscribeId);

            //订单数量
            Integer orderNum = adminSubscribeService.queryOrderNum(startTime,endTime,shopId,subscribeId);

            //商品数量
            Integer goodsNum = adminSubscribeService.queryGoodsNum(startTime,endTime,shopId,subscribeId);

            //三种方式
            Integer selfNum = adminSubscribeService.querySubscribeSelfNum(startTime,endTime,shopId,subscribeId);
            Integer storeNum = adminSubscribeService.querySubscribeStoreNum(startTime,endTime,shopId,subscribeId);
            Integer mailNum = adminSubscribeService.querySubscribeMailNum(startTime,endTime,shopId,subscribeId);

            //订阅价格
            Integer basePrice = adminSubscribeService.querySubscribeBasePrice();

            Double lossAmount = basePrice - totalPrice;

             SubscribeStatisticsVo vo = new SubscribeStatisticsVo(total,userTotal,totalPrice,totalPoint,orderNum,goodsNum,selfNum,storeNum,mailNum,basePrice,lossAmount);

        return ResponseUtil.ok(vo);
    }


    @ApiOperation("根据类型统计")
    @GetMapping("/statisticByType")
    @LogAnno
    public Object statisticByType(String startTime, String endTime, Integer shopId,Integer subscribeId,
                                @RequestParam(defaultValue = "1") Integer page,
                                @RequestParam(defaultValue = "10") Integer limit,
                                @Sort @RequestParam(defaultValue = "add_time") String sort,
                                @Order @RequestParam(defaultValue = "desc") String order){
        //查询所有的订阅，并封装对应的数据

        IPage<LumiereSubscribe> lumiereSubscribeList = lumiereSubscribeService.queryAll(page,limit,sort,order,subscribeId);
        List list = CollUtil.newArrayList();
        lumiereSubscribeList.getRecords().forEach(lumiereSubscribe -> {

            //订阅总数
            CompletableFuture<Integer> totalType=  CompletableFuture.supplyAsync(()->
                 adminSubscribeService.querySubscribeNum(startTime,endTime,shopId,lumiereSubscribe.getId())
            );
            //总人数
            CompletableFuture<Integer> userTotalType=  CompletableFuture.supplyAsync(()->
                    adminSubscribeService.queryUserTotal(startTime,endTime,shopId,lumiereSubscribe.getId())
                    );
            //总额和总积分
            CompletableFuture<Double> totalPriceType=  CompletableFuture.supplyAsync(()->
                            adminSubscribeService.queryTotalPrice(startTime,endTime,shopId,lumiereSubscribe.getId())
                    );
            CompletableFuture<Integer> totalPointType=  CompletableFuture.supplyAsync(()->
                            adminSubscribeService.queryTotalPoint(startTime,endTime,shopId,lumiereSubscribe.getId())
                    );
            //订单数量
            CompletableFuture<Integer> orderNumType=  CompletableFuture.supplyAsync(()->
                     adminSubscribeService.queryOrderNum(startTime,endTime,shopId,lumiereSubscribe.getId())
                    );
            //商品数量
            CompletableFuture<Integer> goodsNumType=  CompletableFuture.supplyAsync(()->
                            adminSubscribeService.queryGoodsNum(startTime,endTime,shopId,lumiereSubscribe.getId())
                    );
            //三种方式
            CompletableFuture<Integer> selfNumType=  CompletableFuture.supplyAsync(()->
                    adminSubscribeService.querySubscribeSelfNum(startTime,endTime,shopId,lumiereSubscribe.getId())
                    );
            CompletableFuture<Integer> storeNumType=  CompletableFuture.supplyAsync(()->
                            adminSubscribeService.querySubscribeStoreNum(startTime,endTime,shopId,lumiereSubscribe.getId())
                    );
            CompletableFuture<Integer> mailNumType=  CompletableFuture.supplyAsync(()->
                    adminSubscribeService.querySubscribeMailNum(startTime,endTime,shopId,lumiereSubscribe.getId())
                    );
            //商品价格
            CompletableFuture<Integer> basePriceType=  CompletableFuture.supplyAsync(()->
                            adminSubscribeService.queryGoodsBasePrice(startTime,endTime,shopId,lumiereSubscribe.getId())
                    );
            //等所有任务执行完成
            CompletableFuture.allOf(totalType,userTotalType,totalPointType,orderNumType,goodsNumType,selfNumType,storeNumType,mailNumType);
            try {
                Double lossAmountType = basePriceType.get() - totalPriceType.get();
                SubscribeStatisticsVo voType = new SubscribeStatisticsVo(totalType.get(),userTotalType.get(),totalPriceType.get(),totalPointType.get(),orderNumType.get(),goodsNumType.get(),selfNumType.get(),storeNumType.get(),mailNumType.get(),basePriceType.get(),lossAmountType);
                voType.setSubscribeId(lumiereSubscribe.getId());
                voType.setSubscribeName(lumiereSubscribe.getName());
                voType.setStartTime(lumiereSubscribe.getStartTime());
                voType.setEndTime(lumiereSubscribe.getEndTime());
                list.add(voType);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
        lumiereSubscribeList.setRecords(list);
        return ResponseUtil.okPage(lumiereSubscribeList);
    }


    @ApiOperation("订阅订单信息")
    @GetMapping("/orderInfo")
    @LogAnno
    public Object orderInfo(@RequestParam(defaultValue = "1") Integer page,
                            @RequestParam(defaultValue = "10") Integer limit, Integer subscribeId, Byte orderType, String userName, Short orderStatus,
                            @RequestParam(required = false)@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")  List<LocalDateTime> dateTime, Integer shopId){

        List<LitemallUser> byName = litemallUserService.findByName(userName);
        IPage<LitemallOrder> orders = litemallOrderService.selectByExample(shopId,dateTime,byName,subscribeId,orderType,orderStatus,page,limit);
        List orderDtos = CollUtil.newArrayList();
        orderDtos = orders.getRecords().stream().map(litemallOrder -> {
            LitemallOrderDto orderDto = new LitemallOrderDto();
            BeanUtils.copyProperties(litemallOrder,orderDto);
            //根据subscribeId查询订阅名称
            LumiereSubscribe lumiereSubscribe = lumiereSubscribeService.findById(litemallOrder.getExternalId());
            orderDto.setSubscribeName(lumiereSubscribe!=null?lumiereSubscribe.getName():null);

            //获取订单对应的商品名称
            List<LitemallOrderGoods> goods =  litemallOrderGoodsService.queryByOid(litemallOrder.getId());
            orderDto.setGoods(goods);
            orderDto.setShopName(ObjectUtil.isNotNull(litemallOrder.getShopId())?litemallShopService.findById(litemallOrder.getShopId()).getName():null);
            String receiptRange = litemallOrder.getReceiptStartTime() + "--" + litemallOrder.getReceiptEndTime();
            orderDto.setReceiptRange(litemallOrder.getReceiptStartTime() != null || litemallOrder.getReceiptEndTime() != null ? receiptRange : null);
            orderDto.setOrderPrice(litemallOrder.getOrderPrice());
            //查询用户邮箱
            LitemallUser litemallUser = litemallUserService.findById(litemallOrder.getUserId());
            orderDto.setEmail(litemallUser != null ? litemallUser.getEmail() : null);
            orderDto.setUserName(litemallUser != null ? litemallUser.getUsername() : null);
            return orderDto;
        }).collect(Collectors.toList());
        orders.setRecords(orderDtos);
        return ResponseUtil.okPage(orders);
    }
}
